package com.dhy.service.imp;

import com.dhy.mapper.PermissionMapper;
import com.dhy.pojo.Permission;
import com.dhy.service.IAutoScanPermissionService;
import com.dhy.utils.ClassUtil;
import com.dhy.utils.annotation.MyPermissionAnnotation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.*;

import java.lang.reflect.AnnotatedElement;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

@Service
public class AutoScanPermissionServiceImpl2 implements IAutoScanPermissionService {

    @Value("${scan.tage}")
    private boolean tage;

    @Value("${scan.scanPackage}")
    private String scanPackage;

    @Autowired
    PermissionMapper permissionMapper;

    @Override
    public void scan() {
        List<Permission> permissionList = new ArrayList<>();
        if (this.tage) {
            permissionMapper.truncate();
            List<Class<?>> controllers = ClassUtil.fileDfs(this.scanPackage);
            for (Class<?> controller : controllers) {
                Permission permission = dfs(controller);
                if(permission == null){
                    continue;
                }
                permission.setSn(controller.getSimpleName());
                Long parentId = permissionMapper.insertSelective(permission);
                System.out.println("parentId =============>"+parentId);
                for(Method method : controller.getMethods()){
                    Permission permissionChild = dfs(method);
                    if(permissionChild == null){
                        continue;
                    }
                    String childUrl = getChildUrl(method);
                    permissionChild.setUrl(permission.getUrl()+childUrl);
                    permissionChild.setSn(controller.getSimpleName()+":"+method.getName());
                    permissionChild.setParentId(parentId);
                    permissionList.add(permissionChild);
                }
            }
        }
        permissionMapper.batchInsert(permissionList);
    }

    public <T extends AnnotatedElement> Permission dfs(T t) {
        MyPermissionAnnotation annotation = t.getAnnotation(MyPermissionAnnotation.class);
        if (annotation != null) {
            Permission permission = new Permission();
            if(t instanceof Class){
                RequestMapping annotationRmp = t.getAnnotation(RequestMapping.class);
                if (annotationRmp != null) {
                    permission.setUrl(annotationRmp.value()[0]);
                }
            }
            permission.setName(annotation.name());
            permission.setDescs(annotation.desc());
            return permission;
        }
        return null;
    }

    private String getChildUrl(Method method) {

        RequestMapping annotation = method.getAnnotation(RequestMapping.class);
        if (annotation != null) {
            return annotation.value().length > 0 ? annotation.value()[0] : "";
        }
        GetMapping getMapping = method.getAnnotation(GetMapping.class);
        if (getMapping != null) {
            return getMapping.value().length > 0 ? getMapping.value()[0] : "";
        }
        PutMapping putMapping = method.getAnnotation(PutMapping.class);
        if (putMapping != null) {
            return putMapping.value().length > 0 ? putMapping.value()[0] : "";
        }
        DeleteMapping deleteMapping = method.getAnnotation(DeleteMapping.class);
        if (deleteMapping != null) {
            return deleteMapping.value().length > 0 ? deleteMapping.value()[0] : "";
        }
        PostMapping postMapping = method.getAnnotation(PostMapping.class);
        if (postMapping != null) {
            return postMapping.value().length > 0 ? postMapping.value()[0] : "";
        }
        PatchMapping patchMapping = method.getAnnotation(PatchMapping.class);
        if (patchMapping != null) {
            return patchMapping.value().length > 0 ? patchMapping.value()[0] : "";
        }
        return "";
    }
}
